package com.wx.sftp.impl;

import com.wx.sftp.SaasFtp;
import com.wx.sftp.VideoUtils;
import com.wx.sftp.config.SaasFtpConf;
import com.wx.sftp.share.SaasDir;
import com.jcraft.jsch.*;
import com.wx.sftp.utils.IOUtils;
import com.wx.sftp.utils.Image;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.function.Function;

/**
 */
@Slf4j
public abstract class BaseSaasFtp implements SaasFtp {
    private SaasFtpConf conf;

    BaseSaasFtp(SaasFtpConf conf) {
        this.conf = conf;
    }

    @Override
    public String upload(InputStream inputStream, SaasDir dir, String fileName) {
        return apply(sftp -> {
            String directory = getCompleteDirPath(dir);
            String dst = directory + "/" + fileName;
            try {
                sftp.put(inputStream, dst, ChannelSftp.OVERWRITE);
            } catch (SftpException e) {
                log.warn("upload throw exception:", e);
                return null;
            }
            return conf.getDomain() + conf.getSecDir() + dir.getPath() + "/" + fileName;
        });
    }

    @Override
    public String uploadVedio(InputStream inputStream, SaasDir dir, String fileName, Boolean needHls) {
        return apply(sftp -> {
            String directory = getCompleteDirPath(dir);
            String dst = directory + "/" + fileName;
            try {
                sftp.put(inputStream, dst, ChannelSftp.OVERWRITE);
                if (VideoUtils.checkContentType(fileName) == 0 && needHls) {
                    String name = fileName.substring(0, fileName.lastIndexOf("."));
                    return directory + "|" + conf.getVideoDomain() + "/" + name + "/" + name + ".m3u8";
                }
            } catch (SftpException e) {
                log.warn("upload throw exception:", e);
                return null;
            }
            return conf.getDomain() + conf.getSecDir() + dir.getPath() + "/" + fileName;
        });
    }

    @Override
    public String uploadBase64Image(String base64Str, SaasDir dir, String fileName) {
        InputStream inputStream = IOUtils.base64ToInputStream(base64Str);
        return upload(inputStream, dir, fileName);
    }

    @Override
    public List<String> batchUploadImage(List<Image> imageList, SaasDir dir) {
        if (imageList == null || imageList.isEmpty()) {
            log.debug("图片内容不能为空");
            return null;
        }
        if (dir == null) {
            log.debug("图片路径不能为空");
            return null;
        }
        List<String> urlList = new ArrayList<>();
        for (Image image : imageList) {
            String base64Str = image.getBase64Code();
            String imageType = image.getImageType();
            if (StringUtils.isBlank(base64Str) || StringUtils.isBlank(imageType)) {
                continue;
            }
            String fileName = System.currentTimeMillis() + imageType;
            InputStream inputStream = IOUtils.base64ToInputStream(base64Str);
            String url = upload(inputStream, dir, fileName);
            //如果url为空，则删除所有的url,并返回null
            if (StringUtils.isBlank(url)) {
                deleteFileByUrl(urlList);
                return null;
            } else {
                urlList.add(url);
            }
        }
        return urlList;
    }

    @Override
    public boolean delete(String file) {
        return Boolean.TRUE.equals(
                apply(
                        sftp -> {
                            try {
                                sftp.rm(file);
                                return true;
                            } catch (SftpException e) {
                                log.warn("delete throw Exception:", e);
                                return false;
                            }
                        }
                )
        );
    }

    @Override
    public boolean delete(String directory, String fileName) {
        return delete(directory + "/" + fileName);
    }

    @Override
    public boolean deleteFileByUrl(String url) {
        return Boolean.TRUE.equals(
                apply(
                        sftp -> {
                            if (url.contains(".m3u8")) {

                                String str = StringUtils.replace(url, conf.getVideoDomain(), "");
                                System.out.println("--------------------");
                                System.out.println(conf.getBaseDir() + "/dev/video/m3u8/" + str.substring(0, str.lastIndexOf("/")));
                                delete(conf.getBaseDir() + "/dev/video/m3u8/" + str.substring(0, str.lastIndexOf("/")));
                                System.out.println(conf.getBaseDir() + "/dev/video/" + str.substring(str.lastIndexOf("/"), str.lastIndexOf(".")) + ".*");
                                return delete(conf.getBaseDir() + "/dev/video/" + str.substring(str.lastIndexOf("/"), str.lastIndexOf(".")) + ".*");
                            } else {
                                String s = StringUtils.replace(url, conf.getDomain(), "");
                                String path = conf.getBaseDir() + s;
                                return delete(path);
                            }

                        }
                )
        );
    }

    @Override
    public void deleteFileByUrl(List<String> urls) {
        if (CollectionUtils.isEmpty(urls)) {
            return;
        }
        for (String url : urls) {
            deleteFileByUrl(url);
        }
    }

    @Override
    public InputStream download(String directory, String fileName) {
        return download(directory + "/" + fileName);
    }

    @Override
    public InputStream download(String file) {
        return apply(sftp -> {
            try {
                return sftp.get(file);
            } catch (SftpException e) {
                log.warn("download throw Exception:", e);
                return null;
            }
        });
    }

    @Override
    public boolean dirIsExist(String directory) {
        return Boolean.TRUE.equals(
                apply(
                        sftp -> {
                            try {
                                SftpATTRS sftpATTRS = sftp.lstat(directory);
                                return sftpATTRS.isDir();
                            } catch (Exception e) {
                                log.debug("Dir is not exist:{}", e.getMessage());
                                return false;
                            }
                        }
                )
        );
    }

    @Override
    public boolean dirIsNotExist(String directory) {
        return !dirIsExist(directory);
    }

    @Override
    public boolean mkdir(String directory) {
        return Boolean.TRUE.equals(
                apply(
                        sftp -> {
                            try {
                                sftp.mkdir(directory);
                                return true;
                            } catch (SftpException e) {
                                log.debug("mkdir throw Exception:", e);
                                return false;
                            }
                        }
                )
        );
    }

    @Override
    public boolean clearDir(String directory) {
        return Boolean.TRUE.equals(
                apply(
                        sftp -> {
                            try {
                                // 首先删除文件夹下的所有文件然后在删除文件夹
                                sftp.rm(directory + "/*");
                                return true;
                            } catch (SftpException e) {
                                log.debug("rmdir throw Exception:", e);
                                return false;
                            }
                        }
                )
        );
    }

    @Override
    public boolean rmdir(String directory) {
        return Boolean.TRUE.equals(
                apply(
                        sftp -> {
                            try {
                                // 首先删除文件夹下的所有文件然后在删除文件夹
                                sftp.rm(directory + "/*");
                                // 删除文件夹只能删除空文件夹
                                sftp.rmdir(directory);
                                return true;
                            } catch (SftpException e) {
                                log.debug("rmdir throw Exception:", e);
                                return false;
                            }
                        }
                )
        );
    }

    @Override
    public Vector ls(String path) {
        return
                apply(
                        sftp -> {
                            try {
                                // 删除文件夹只能删除空文件夹
                                return sftp.ls(path);
                            } catch (SftpException e) {
                                log.debug("rmdir throw Exception:", e);
                                return null;
                            }
                        }
                );
    }
    public boolean fstpmv(String command) {
        return
                Boolean.TRUE.equals(apply(
                        sftp -> {
                            try {
                                Channel channel =  sftp.getSession().openChannel("exec");
                                ChannelExec    channelExec = (ChannelExec) channel;
                                channelExec.setCommand(command);
                                channelExec.connect();

                              //  channelExec.setInputStream(null);
                                InputStream in = channelExec.getInputStream();
                                BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                                String buf = null;
                                while ((buf = reader.readLine()) != null)
                                {
                                    System.out.println(buf);
                                }
                                reader.close();
                                return true;
                            } catch (Exception e) {
                                log.debug("rmdir throw Exception:", e);
                                return false;
                            }
                        }
                ));
    }
    /**
     * 通过SaasDir获取文件夹在服务器中的绝对路径
     *
     * @param dir SaasDir
     * @return 绝对路径
     */
    private String getCompleteDirPath(SaasDir dir) {
        return conf.getBaseDir() + conf.getSecDir() + dir.getPath();
    }

    private String createIosPlist(String version, String ipaUrl) {
        return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +
                "<plist version=\"1.0\">\n" +
                "\t<dict>\n" +
                "\t\t<key>items</key>\n" +
                "\t\t<array>\n" +
                "\t\t\t<dict>\n" +
                "\t\t\t\t<key>assets</key>\n" +
                "\t\t\t\t<array>\n" +
                "\t\t\t\t\t<dict>\n" +
                "\t\t\t\t\t\t<key>kind</key>\n" +
                "\t\t\t\t\t\t<string>software-package</string>\n" +
                "\t\t\t\t\t\t<key>url</key>\n" +
                "\t\t\t\t\t\t<string>" + ipaUrl + "</string>\n" +
                "\t\t\t\t\t</dict>\n" +
                "\t\t\t\t</array>\n" +
                "\t\t\t\t<key>metadata</key>\n" +
                "\t\t\t\t<dict>\n" +
                "\t\t\t\t\t<key>bundle-identifier</key>\n" +
                "\t\t\t\t\t<string>com.chinatelecom.XiongAnBGiphone</string>\n" +
                "\t\t\t\t\t<key>bundle-version</key>\n" +
                "\t\t\t\t\t<string>" + version + "</string>\n" +
                "\t\t\t\t\t<key>kind</key>\n" +
                "\t\t\t\t\t<string>software</string>\n" +
                "\t\t\t\t\t<key>title</key>\n" +
                "\t\t\t\t\t<string>物联网</string>\n" +
                "\t\t\t\t</dict>\n" +
                "\t\t\t</dict>\n" +
                "\t\t</array>\n" +
                "\t</dict>\n" +
                "</plist>";
    }

    /**
     * 将变化的部分抽取为 function
     *
     * @param function function
     * @param <R>      返回结果
     * @return 返回结果
     */
    @Nullable
    abstract <R> R apply(Function<ChannelSftp, R> function);


}
